import * as THREE from "../../../modules/three/three.module.js";
import {getModelNameFromUrl, gltfLoader} from "../util/Utils.js";
import BoxFrameMesh from "../lib/gadget/BoxFrameMesh.js";

const hoverColor = '#00f5f5';
const defaultColor = '#2b47ff';

export default class ModelEntity extends THREE.Group {
  /**
   * @type {ModelVO}
   */
  vo
  boundingBox = new THREE.Box3()
  onGltfLoaded
  size = new THREE.Vector3()
  /**
   * @type {THREE.Mesh}
   */
  modelMesh = new THREE.Mesh()

  scanLineGroup = new THREE.Group()
  boundingFrame = new BoxFrameMesh(defaultColor)


  constructor(vo, glbMap, modelLoaded) {
    super();
    this.vo = vo;
    this.glbMap = glbMap;
    this.position.copy(vo.position);
    this.scale.copy(vo.scale);
    this.rotation.copy(vo.rotation);
    this.boundingBox.min.set(-0.5, -0.5, 0);
    this.boundingBox.max.set(0.5, 0.5, 1);
    this.onGltfLoaded = modelLoaded;
    this.init();
    this.visible = vo.visible
  }

  init() {
    const gScene = this.glbMap.get(this.vo.getUrl());
    if (gScene) {
      const clonedMesh = gScene.clone();
      clonedMesh.traverse(obj3d => {
        if (obj3d.material) {
          obj3d.material = obj3d.material.clone();
        }
      });
      this.onGltfLoadFinish(clonedMesh);
    } else {
      gltfLoader.load(this.vo.getUrl(), (gltf) => {
        gltf.scene.rotation.x = Math.PI * 0.5;
        this.onGltfLoadFinish(gltf.scene,gltf);
        // this.glbMap.set(this.vo.url, gltf.scene);
      });
    }
  }

  onGltfLoadFinish(gltfScene, gltf) {
    this.boundingBox.setFromObject(gltfScene);
    this.boundingBox.getSize(this.size);
    this.boundingFrame.update(this.boundingBox);
    this.add(this.boundingFrame);
    this.add(gltfScene);
    this.modelMesh = gltfScene;

    const isLand = this.vo.isLand
    this.modelMesh.traverse(it => {
      if (isLand) {
        it.receiveShadow = true;
        it.castShadow = false;
      } else {
        it.receiveShadow = false;
        it.castShadow = true;
      }
      if (it.geometry) {
        it.geometry.computeVertexNormals();
      }
    })

    this.toggleVisible(this.vo.visible);
    const scanLineGroup = this.scanLineGroup;
    scanLineGroup.copy(gltfScene, true);
    this.add(scanLineGroup);

    if (this.onGltfLoaded) {
      this.onGltfLoaded(gltfScene, this.boundingBox);
    }
  }

  toggleBoundingFrame(show) {
    this.boundingFrame.visible = show;
  }

  toggleVisible(show) {
    this.boundingFrame.visible = !show;
    this.modelMesh.visible = show;
  }

  setLocked(locked) {
    this.vo.locked = locked
    if (locked) {
      this.toggleBoundingFrame(false)
    }
  }

  get locked() {
    return this.vo.locked
  }

  get content() {
    return getModelNameFromUrl(this.vo.url) + ' ' + this.vo.id;
  }

}
